package com.xyzwps.ewa.modules.auth.session

import com.xyzwps.ewa.data.database
import com.xyzwps.ewa.modules.user.User
import com.xyzwps.ewa.modules.user.UserId
import com.xyzwps.ewa.modules.user.UserRepository.UserTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.javatime.datetime
import org.jetbrains.exposed.sql.transactions.transaction

object RdbSessionRepository {
    object SessionTable : Table(name = "sessions") {
        val id = varchar("id", length = 64)
        val userId = long("user_id")
        val start = datetime("start")
        val end = datetime("end")

        override val primaryKey = PrimaryKey(id)

        init {
            index(customIndexName = "idx_user_id", columns = arrayOf(userId))
        }
    }

    init {
        transaction {
            SchemaUtils.create(SessionTable)
        }
    }

    fun create(session: Session) {
        SessionTable.insert {
            it[id] = session.sessionId
            it[userId] = session.userId.value
            it[start] = session.start
            it[end] = session.end
        }
    }

    fun find(sessionId: String) = SessionTable.selectAll()
        .where { SessionTable.id eq sessionId }
        .map(this::toSession)
        .firstOrNull()

    fun update(session: Session) = SessionTable.update({ SessionTable.id eq session.sessionId }) {
        it[start] = session.start
        it[end] = session.end
    }

    private fun toSession(row: ResultRow) = Session(
        sessionId = row[SessionTable.id],
        userId = UserId(row[SessionTable.userId]),
        start = row[SessionTable.start],
        end = row[SessionTable.end]
    )

    fun delete(sessionId: String) = SessionTable.deleteWhere { id eq sessionId }
}